package test.demo;

import cn.hutool.core.util.ArrayUtil;
import tech.waterism.modelbase.PredictBase;
import tech.waterism.modelbase.PredictResult;
import com.alibaba.fastjson.JSON;

import java.time.LocalDateTime;
import java.util.*;

/**
 * 降雨径流相关图(P-Pa-R)模型
 * 累积算法考虑预报时刻Pa
 *
 * @author 初京刚
 * @version 2.0
 */
public class P_RZHJR extends PredictBase {

    /**
     * 前期土壤含水量
     */
    private double paInitial;

    /**
     * 查线方式代码，等于1表示用累计雨量查曲线，不等于1表示用时段雨量查曲线
     */
    private int calculatedType;

    /**
     * 土壤最大初损量Im
     */
    private double im;

    /**
     * 12个月的土壤含水量日衰减系数KD
     */
    private double[] kd;

    /**
     * P~R曲线条数N
     */
    private int n;

    /**
     * 每条P～R曲线对应的Pa值
     */
    private double[] pa;

    /**
     * P～R曲线的节点数M
     */
    private int m;

    /**
     * P～R曲线
     */
    private double[][] pr;

    /**
     * 降水时间
     */
    private Date[] floodTm;

    /**
     * 预报开始时间
     */
    private Date startTm;

    /**
     * 预报开始数组下标
     */
    private int startIndex;

    /**
     * 降水量
     */
    private double[] floodDrp;

    /**
     * 降水序列长度
     */
    private Integer floodRainRange;

    /**
     * 降水时段长
     */
    private double timeInterval;

    /**
     * 土壤含水量模拟过程
     */
    private double[] paSim;

    /**
     * 模拟总产流
     */
    private double[] runoffSim;


    public P_RZHJR(Map<String, String> data) {
        super();
        paInitial = Double.parseDouble(data.get("PA0"));                        // 前期土壤含水量
        calculatedType = Integer.parseInt(data.get("CalculatedType"));         // line 3 查曲线方式代码，等于1表示用累计雨量查曲线，不等于1表示用时段雨量查曲线
        im = Double.parseDouble(data.get("Im"));                               // line 4 土壤最大初损量Im
        kd = JSON.parseObject(data.get("KD"), double[].class);                 // line 5 12个月的土壤含水量日衰减系数KD
        n = Integer.parseInt(data.get("N"));                                   // line 6 P～R曲线条数N
        pa = JSON.parseObject(data.get("Pa"), double[].class);                 // line 7 每条P～R曲线对应的Pa值
        m = Integer.parseInt(data.get("M"));                                   // line 8 P～R曲线的节点数M
        pr = JSON.parseObject(data.get("PR"), double[][].class);               // line 9 开始取到最后 P～R曲线：其中第1列为序号 需要去掉; 第2列为降雨
        floodTm = JSON.parseObject(data.get("dt"), Date[].class);              // input[i].data.dt
        startTm  = JSON.parseObject(data.get("start"), Date.class);
        startIndex = ArrayUtil.indexOf(floodTm, startTm);
        floodDrp = JSON.parseObject(data.get("rain"), double[].class);         // input[i].data.rain
        floodRainRange = floodDrp.length;                                      //
        timeInterval = Double.parseDouble(data.get("clen"));                   // index.clen
        paSim = new double[floodRainRange + 1];
        runoffSim = new double[floodRainRange];
    }

    /**
     * 模型计算
     */
    public Map<String, double[]> PRZHJRmodel() {

        //降雨径流相关图计算
        ppar();

        Map<String, double[]> simulationResult = new HashMap<>();

        simulationResult.put("rain", floodDrp);
        simulationResult.put("runoffSim", runoffSim);
        return simulationResult;
    }


    /**
     * 降雨径流相关图
     *
     * @return 产流
     */
    private void ppar() {
        double sumR1 = 0, sumR2 = 0, paa, sumP1 = 0, sumP2 = 0;
        int j_pa = 0; //标记Pa插值点
        int j_pa_1; //Pa下限
        int j_pa_2; //Pa上限
        int j_pa_mark;// 标记是否插值
        paSim[0] = paInitial;
        if(calculatedType != 1) {
            for (int i = 0; i < floodRainRange; i++){
                j_pa_mark = 0;
                sumP1 = floodDrp[i];
                paa = paSim[i]; //前期影响净雨
                if(paa > pa[pa.length - 1]) {
                    j_pa = pa.length - 1;
                    j_pa_mark = 1; //不用插值
                } else {
                    for (int j = pa.length - 1; j >= 0; j--){
                        if (Math.abs(paa - pa[j]) < 0.0001) { //几乎相等
                            j_pa = j;
                            j_pa_mark = 1; //不用差值
                        }else if (paa < pa[j]) {
                            j_pa = j - 1;
                            if (j_pa < 0) {
                                j_pa = 0;
                            }
                        }
                    }
                }
                if (j_pa == 0) {
                    if (paa < pa[j_pa]) {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa;
                    }else {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa + 1;
                    }
                } else if(j_pa == pa.length - 1){
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa;
                } else {
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa + 1;
                }
                if(j_pa_mark != 1) {
                    if(j_pa_1 == j_pa_2){
                        sumR2 = calculateR(sumP1, pr[0], pr[j_pa_1 + 1], pr[0].length);
                    }else{
                        double temp1 = calculateR(sumP1, pr[0], pr[j_pa_1 + 1], pr[j_pa_1 + 1].length);
                        double temp2 = calculateR(sumP1, pr[0], pr[j_pa_2 + 1], pr[j_pa_2 + 1].length);
                        sumR2 = (temp2 * (paa - pa[j_pa_1]) + temp1 * (pa[j_pa_2] - paa)) / (pa[j_pa_2] - pa[j_pa_1]);
                    }
                    if (sumR2 < 0) {
                        sumR2 = 0;
                    }
                } else {
                    sumR2 = calculateR(sumP1, pr[0], pr[j_pa + 1], pr[j_pa + 1].length);
                }
                if (sumR2 < 0) {
                    runoffSim[i] = 0;
                } else if (sumR2 > floodDrp[i]) {
                    runoffSim[i] = floodDrp[i];
                } else {
                    runoffSim[i] = sumR2;
                }
                Calendar time = Calendar.getInstance();
                time.setTime(floodTm[i]);
                Integer month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份

                double ka0 = kd[month - 1];
                double D = 24 / timeInterval;
                double ka = Math.pow(ka0,1.0/D);

                /*需保留最后一个时段末的状态值，去掉时段初值限制条件*/
//                if(i + 1 < floodRainRange){
                paSim[i + 1] = ka * (paSim[i] + floodDrp[i]);
                if (paSim[i + 1] >= im) {
                    paSim[i + 1] = im;
                }
                //                }
            }
        } else {
            if (startIndex == 0) {
                j_pa_mark = 0;
                paa = paSim[startIndex]; //前期影响净雨
                if (paa > pa[pa.length - 1]) {
                    j_pa = pa.length - 1;
                    j_pa_mark = 1; //不用插值
                } else {
                    for (int j = pa.length - 1; j >= 0; j--){
                        if (Math.abs(paa - pa[j]) < 0.0001) { //几乎相等
                            j_pa = j;
                            j_pa_mark = 1; //不用差值
                        }else if (paa < pa[j]) {
                            j_pa = j - 1;
                            if (j_pa < 0) {
                                j_pa = 0;
                            }
                        }
                    }
                }
                if (j_pa == 0) {
                    if (paa < pa[j_pa]) {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa;
                    }else {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa + 1;
                    }
                }else if(j_pa == pa.length - 1){
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa;
                } else {
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa + 1;
                }
                for (int i = 0; i < floodRainRange; i++){
                    sumP2 += floodDrp[i];
                    if(j_pa_mark != 1) {
                        if(j_pa_1 == j_pa_2){
                            sumR2 = calculateR(sumP2, pr[0], pr[j_pa_1 + 1], pr[0].length);
                        }else{
                            double temp1 = calculateR(sumP2, pr[0], pr[j_pa_1 + 1], pr[j_pa_1 + 1].length);
                            double temp2 = calculateR(sumP2, pr[0], pr[j_pa_2 + 1], pr[j_pa_2 + 1].length);
                            sumR2 = (temp2 * (paa - pa[j_pa_1]) + temp1 * (pa[j_pa_2] - paa)) / (pa[j_pa_2] - pa[j_pa_1]);
                        }
                        if (sumR2 < 0) {
                            sumR2 = 0;
                        }
                    } else {
                        sumR2 = calculateR(sumP2, pr[0], pr[j_pa + 1], pr[j_pa + 1].length);
                    }
                    runoffSim[i] = sumR2 - sumR1;
                    if (runoffSim[i] < 0) {
                        runoffSim[i] = 0;
                    }
                    if (runoffSim[i] > floodDrp[i]) {
                        runoffSim[i] = floodDrp[i];
                    }
                    sumR1 = sumR2;

                    Calendar time = Calendar.getInstance();
                    time.setTime(floodTm[i]);
                    Integer month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份
                    double ka0 = kd[month - 1];
                    double D = 24 / timeInterval;
                    double ka = Math.pow(ka0,1.0/D);

                    /*需保留最后一个时段末的状态值，去掉时段初值限制条件*/
//                if(i + 1 < floodRainRange){
                    paSim[i + 1] = ka * (paSim[i] + floodDrp[i]);
                    if (paSim[i + 1] >= im) {
                        paSim[i + 1] = im;
                    }
                }
            } else {
                j_pa_mark = 0;
                paa = paSim[0]; //前期影响净雨
                if (paa > pa[pa.length - 1]) {
                    j_pa = pa.length - 1;
                    j_pa_mark = 1; //不用插值
                } else {
                    for (int j = pa.length - 1; j >= 0; j--){
                        if (Math.abs(paa - pa[j]) < 0.0001) { //几乎相等
                            j_pa = j;
                            j_pa_mark = 1; //不用差值
                        }else if (paa < pa[j]) {
                            j_pa = j - 1;
                            if (j_pa < 0) {
                                j_pa = 0;
                            }
                        }
                    }
                }
                if (j_pa == 0) {
                    if (paa < pa[j_pa]) {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa;
                    }else {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa + 1;
                    }
                }else if(j_pa == pa.length - 1){
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa;
                } else {
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa + 1;
                }
                for (int i = 0; i < startIndex; i++) {
                    sumP1 += floodDrp[i];
                    if (j_pa_mark != 1) {
                        if (j_pa_1 == j_pa_2) {
                            sumR2 = calculateR(sumP1, pr[0], pr[j_pa_1 + 1], pr[0].length);
                        } else {
                            double temp1 = calculateR(sumP1, pr[0], pr[j_pa_1 + 1], pr[j_pa_1 + 1].length);
                            double temp2 = calculateR(sumP1, pr[0], pr[j_pa_2 + 1], pr[j_pa_2 + 1].length);
                            sumR2 = (temp2 * (paa - pa[j_pa_1]) + temp1 * (pa[j_pa_2] - paa)) / (pa[j_pa_2] - pa[j_pa_1]);
                        }
                        if (sumR2 < 0) {
                            sumR2 = 0;
                        }
                    } else {
                        sumR2 = calculateR(sumP1, pr[0], pr[j_pa + 1], pr[j_pa + 1].length);
                    }
                    runoffSim[i] = sumR2 - sumR1;
                    if (runoffSim[i] < 0) {
                        runoffSim[i] = 0;
                    }
                    if (runoffSim[i] > floodDrp[i]) {
                        runoffSim[i] = floodDrp[i];
                    }
                    sumR1 = sumR2;

                    Calendar time = Calendar.getInstance();
                    time.setTime(floodTm[i]);
                    Integer month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份
                    double ka0 = kd[month - 1];
                    double D = 24 / timeInterval;
                    double ka = Math.pow(ka0, 1.0 / D);

                    /*需保留最后一个时段末的状态值，去掉时段初值限制条件*/
//                if(i + 1 < floodRainRange){
                    paSim[i + 1] = ka * (paSim[i] + floodDrp[i]);
                    if (paSim[i + 1] >= im) {
                        paSim[i + 1] = im;
                    }
                }

                j_pa_mark = 0;
                paa = paSim[startIndex]; //前期影响净雨
                if (paa > pa[pa.length - 1]) {
                    j_pa = pa.length - 1;
                    j_pa_mark = 1; //不用插值
                } else {
                    for (int j = pa.length - 1; j >= 0; j--){
                        if (Math.abs(paa - pa[j]) < 0.0001) { //几乎相等
                            j_pa = j;
                            j_pa_mark = 1; //不用差值
                        }else if (paa < pa[j]) {
                            j_pa = j - 1;
                            if (j_pa < 0) {
                                j_pa = 0;
                            }
                        }
                    }
                }
                if (j_pa == 0) {
                    if (paa < pa[j_pa]) {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa;
                    }else {
                        j_pa_1 = j_pa;
                        j_pa_2 = j_pa + 1;
                    }
                }else if(j_pa == pa.length - 1){
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa;
                } else {
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa + 1;
                }
                for (int i = startIndex; i < floodRainRange; i++) {
                        sumP2 += floodDrp[i];
                        if(j_pa_mark != 1) {
                            if(j_pa_1 == j_pa_2){
                                sumR2 = calculateR(sumP2, pr[0], pr[j_pa_1 + 1], pr[0].length);
                            }else{
                                double temp1 = calculateR(sumP2, pr[0], pr[j_pa_1 + 1], pr[j_pa_1 + 1].length);
                                double temp2 = calculateR(sumP2, pr[0], pr[j_pa_2 + 1], pr[j_pa_2 + 1].length);
                                sumR2 = (temp2 * (paa - pa[j_pa_1]) + temp1 * (pa[j_pa_2] - paa)) / (pa[j_pa_2] - pa[j_pa_1]);
                            }
                            if (sumR2 < 0) {
                                sumR2 = 0;
                            }
                        } else {
                            sumR2 = calculateR(sumP2, pr[0], pr[j_pa + 1], pr[j_pa + 1].length);
                        }
                        runoffSim[i] = sumR2 - sumR1;
                        if (runoffSim[i] < 0) {
                            runoffSim[i] = 0;
                        }
                        if (runoffSim[i] > floodDrp[i]) {
                            runoffSim[i] = floodDrp[i];
                        }
                        sumR1 = sumR2;

                        Calendar time = Calendar.getInstance();
                        time.setTime(floodTm[i]);
                        Integer month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份
                        double ka0 = kd[month - 1];
                        double D = 24 / timeInterval;
                        double ka = Math.pow(ka0,1.0/D);

                        /*需保留最后一个时段末的状态值，去掉时段初值限制条件*/
//                if(i + 1 < floodRainRange){
                        paSim[i + 1] = ka * (paSim[i] + floodDrp[i]);
                        if (paSim[i + 1] >= im) {
                            paSim[i + 1] = im;
                        }
                    }
                }
            }

        /*
        for (int i = 0; i < floodRainRange; i++){
            j_pa_mark = 0;
            if (calculatedType != 1){// 每次根据重新计算的pa进行计算
                sumP = floodDrp[i];
                sumR1 = 0;
                paa = paSim[i]; //前期影响净雨
            }else{
                sumP += floodDrp[i];
                paa = paInitial;
            }
            if (paa > pa[pa.length - 1]) {
                j_pa = pa.length - 1;
                j_pa_mark = 1; //不用插值
            } else {
                for (int j = pa.length - 1; j >= 0; j--){
                    if (Math.abs(paa - pa[j]) < 0.0001) { //几乎相等
                        j_pa = j;
                        j_pa_mark = 1; //不用差值
                    }else if (paa < pa[j]) {
                        j_pa = j - 1;
                        if (j_pa < 0) {
                            j_pa = 0;
                        }
                    }
                }
            }

            if (j_pa == 0) {
                if (im >= pa[i]) {
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa;
                }else {
                    j_pa_1 = j_pa;
                    j_pa_2 = j_pa + 1;
                }
            }else {
                j_pa_1 = j_pa;
                j_pa_2 = j_pa + 1;
            }
            if (j_pa_mark != 1) {
                double temp1 = calculateR(sumP, pr[0], pr[j_pa_1 + 1], pr[j_pa_1 + 1].length);
                double temp2 = calculateR(sumP, pr[0], pr[j_pa_2 + 1], pr[j_pa_2 + 1].length);

                if(j_pa_1 == j_pa_2){
                    sumR2 = calculateR(sumP, pr[0], pr[j_pa_1 + 1], pr[0].length);
                }else{
                    sumR2 = (temp2 * (paa - pa[j_pa_1]) +
                                    temp1 * (pa[j_pa_2] - paa)) /
                                    (pa[j_pa_2] - pa[j_pa_1]);
                }

                if (sumR2 < 0) {
                    sumR2 = 0;
                }
            }else {
                sumR2 = calculateR(sumP, pr[0], pr[j_pa], pr[j_pa].length);
            }
            runoffSim[i] = sumR2 - sumR1;
            if (runoffSim[i] < 0) {
                runoffSim[i] = 0;
            }
            if (runoffSim[i] > floodDrp[i]) {
                runoffSim[i] = floodDrp[i];
            }

            Calendar time = Calendar.getInstance();
            time.setTime(floodTm[i]);
            Integer month = time.get(Calendar.MONTH) + 1; // 获得降雨开始月份

            double ka0 = kd[month - 1];
            double ka = 1.0f - (1.0f - ka0) / (24.0f / timeInterval);
            if(i + 1 < floodRainRange){
                paSim[i + 1] = ka * (paSim[i] + floodDrp[i]);
                if (paSim[i + 1] >= im){
                    paSim[i + 1] = im;
                }
            }
            sumR1 = sumR2;
        }
         */

    }

    /**
     * 插值计算径流量
     *
     * @param p 降雨量
     * @param ppa P-R曲线降雨序列
     * @param pr P-R曲线净雨序列
     * @param i_pr P-R曲线降雨序列长度
     * @return 一个与降雨量对应的净雨
     */
    private double calculateR(double p, double[] ppa, double[] pr, int i_pr)
    {
        double rsim = insert2(p, ppa, pr, i_pr);
        if (rsim > p) {
            rsim = p;
        }
        if (rsim < 0) {
            rsim = 0;
        }
        return rsim;
    }

    /**
     * 插值计算
     *
     * @param x0
     * @param x
     * @param y
     * @param n
     * @return
     */
    public double insert2(double x0, double x[], double y[], int n) { // 两点插值(float)
        if (n <= 1) {
            return 0;
        }
        int i;
        double y0, x1, x2;
        if (x[0] < x[n - 1]) { // *x[] is ascending
            for (i = 0; i < n; i++) {
                if (x0 <= x[i]) {
                    break;
                }
            }
        } else { // *x[] is descending
            for (i = 0; i < n; i++) {
                if (x0 >= x[i]) {
                    break;
                }
            }
        }
        if (i >= n - 1) {
            i = n - 2;
        } else if (i <= 1) {
            i = 0;
        } else {
            i--;
        }
        x1 = x[i];
        x2 = x[i + 1];
        if (x1 == x2) {
            return y[i];
        }
        y0 = y[i] + (x0 - x1) / (x2 - x1) * (y[i + 1] - y[i]);

        return y0;
    }

    private List<String> toStringList(double[] array0){
        String[] array = new String[array0.length];
        for(int i = 0; i < array.length; i++){
            array[i] = String.valueOf(array0[i]);
        }
        return Arrays.asList(array);
    }

    @Override
    public void init() {

    }

    @Override
    public PredictResult predict() {
        PredictResult result = new PredictResult();
        Map<String, double[]> map = PRZHJRmodel();
        double[][] RSim = new double[1][];
        RSim[0] = map.get("runoffSim");

        result.setRunoffSim(map.get("runoffSim"));
        result.setRSim(RSim);

        // 更新状态
        List<String> PA = toStringList(paSim);
        Map<String, List<String>> status = new HashMap<>();
        status.put("PA0", PA);
        result.setNewStatus(status);
        return result;
    }

    public static void main(String[] args) {
        String a = "{\"rain\":\"[0.0,0.335055,0.071987,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.627063,5.169758,1.7083660000000003,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.7354319999999999,0.0,0.0,0.115091,0.0,0.0,1.6399359999999998,8.925521,11.492747999999999,0.244204,1.120112,0.0,0.0,0.0,0.0,2.6982269999999997,14.664842,1.5832630000000003,0.128465,0.058328,0.071987,0.49068,0.9925879999999999,0.188842,0.517614,0.188842,0.0,0.663878,1.72426,0.100035,0.114132,0.114132,0.33627,0.9271929999999999,1.033858,0.746713,0.468666,0.0,0.0,0.0,0.688287,0.0,0.0,0.0,0.072186,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.2899965,1.4904165,0.8034654999999999,0.2899965,0.41925799999999996,0.158363,0.0,0.17246,0.34629,1.956547,0.0,0.0,0.0,0.0,0.0,0.559743,3.027328,0.0,0.0,0.0,3.6913460000000002,4.682898,5.856301,1.831605,2.055974,6.422392,0.334275,0.473204,0.0,6.838713999999999,4.284199,0.1114,0.23468999999999998,0.21524000000000001,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.734668,0.185312,0.37483299999999997,0.934054,0.740728,0.190301,3.436601,2.406556,5.554429999999999,0.068526,0.82398,0.072186,0.433116,0.067011,0.0,0.860027,0.455714,0.0,0.126854,0.067011,0.0,0.071987,0.118865,0.359935,0.20007,0.0,10.775335,2.289762,16.446158,3.9358580000000005,2.4487940000000004,0.151686,0.0,0.0,0.0,0.288744,7.935606999999999,0.0,0.0,0.684792,0.228264,0.737121,0.056279]\",\"PR\":\"[[0.0,10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,110.0,120.0,130.0,140.0,150.0,160.0,170.0,180.0,190.0,200.0,210.0,220.0,230.0,240.0],[0.0,0.5,1.0,1.5,2.1,3.0,3.6,4.3,5.0,5.8,6.7,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,89.8],[0.0,0.7,1.3,1.9,2.6,3.6,4.3,5.0,5.8,6.7,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,95.7],[0.0,0.9,1.6,2.3,3.1,4.2,5.0,5.8,6.7,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,101.6],[0.0,1.1,1.9,2.7,3.6,5.0,5.8,6.7,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,107.5],[0.0,1.3,2.2,3.2,4.2,5.8,6.7,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,113.4],[0.0,1.5,2.6,3.7,5.1,6.8,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,107.5,119.3],[0.0,1.7,3.0,4.5,6.4,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,107.5,113.4,125.3],[0.0,1.9,3.5,5.8,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,107.5,113.4,119.3,131.3],[0.0,2.6,5.2,8.3,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,107.5,113.4,119.3,125.3,137.3],[0.0,3.8,7.5,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,107.5,113.4,119.3,125.3,131.3,143.3],[0.0,6.0,12.0,17.9,23.8,29.8,35.8,41.8,47.8,53.5,59.8,65.8,71.8,77.8,83.8,89.8,95.7,101.6,107.5,113.4,119.3,125.3,131.3,137.3,149.3]]\",\"Im\":\"100\",\"start\":\"\\\"2021-07-05 08:00:00\\\"\",\"M\":\"25\",\"N\":\"11\",\"dt\":\"[\\\"2021-06-05 08:00:00\\\",\\\"2021-06-05 14:00:00\\\",\\\"2021-06-05 20:00:00\\\",\\\"2021-06-06 02:00:00\\\",\\\"2021-06-06 08:00:00\\\",\\\"2021-06-06 14:00:00\\\",\\\"2021-06-06 20:00:00\\\",\\\"2021-06-07 02:00:00\\\",\\\"2021-06-07 08:00:00\\\",\\\"2021-06-07 14:00:00\\\",\\\"2021-06-07 20:00:00\\\",\\\"2021-06-08 02:00:00\\\",\\\"2021-06-08 08:00:00\\\",\\\"2021-06-08 14:00:00\\\",\\\"2021-06-08 20:00:00\\\",\\\"2021-06-09 02:00:00\\\",\\\"2021-06-09 08:00:00\\\",\\\"2021-06-09 14:00:00\\\",\\\"2021-06-09 20:00:00\\\",\\\"2021-06-10 02:00:00\\\",\\\"2021-06-10 08:00:00\\\",\\\"2021-06-10 14:00:00\\\",\\\"2021-06-10 20:00:00\\\",\\\"2021-06-11 02:00:00\\\",\\\"2021-06-11 08:00:00\\\",\\\"2021-06-11 14:00:00\\\",\\\"2021-06-11 20:00:00\\\",\\\"2021-06-12 02:00:00\\\",\\\"2021-06-12 08:00:00\\\",\\\"2021-06-12 14:00:00\\\",\\\"2021-06-12 20:00:00\\\",\\\"2021-06-13 02:00:00\\\",\\\"2021-06-13 08:00:00\\\",\\\"2021-06-13 14:00:00\\\",\\\"2021-06-13 20:00:00\\\",\\\"2021-06-14 02:00:00\\\",\\\"2021-06-14 08:00:00\\\",\\\"2021-06-14 14:00:00\\\",\\\"2021-06-14 20:00:00\\\",\\\"2021-06-15 02:00:00\\\",\\\"2021-06-15 08:00:00\\\",\\\"2021-06-15 14:00:00\\\",\\\"2021-06-15 20:00:00\\\",\\\"2021-06-16 02:00:00\\\",\\\"2021-06-16 08:00:00\\\",\\\"2021-06-16 14:00:00\\\",\\\"2021-06-16 20:00:00\\\",\\\"2021-06-17 02:00:00\\\",\\\"2021-06-17 08:00:00\\\",\\\"2021-06-17 14:00:00\\\",\\\"2021-06-17 20:00:00\\\",\\\"2021-06-18 02:00:00\\\",\\\"2021-06-18 08:00:00\\\",\\\"2021-06-18 14:00:00\\\",\\\"2021-06-18 20:00:00\\\",\\\"2021-06-19 02:00:00\\\",\\\"2021-06-19 08:00:00\\\",\\\"2021-06-19 14:00:00\\\",\\\"2021-06-19 20:00:00\\\",\\\"2021-06-20 02:00:00\\\",\\\"2021-06-20 08:00:00\\\",\\\"2021-06-20 14:00:00\\\",\\\"2021-06-20 20:00:00\\\",\\\"2021-06-21 02:00:00\\\",\\\"2021-06-21 08:00:00\\\",\\\"2021-06-21 14:00:00\\\",\\\"2021-06-21 20:00:00\\\",\\\"2021-06-22 02:00:00\\\",\\\"2021-06-22 08:00:00\\\",\\\"2021-06-22 14:00:00\\\",\\\"2021-06-22 20:00:00\\\",\\\"2021-06-23 02:00:00\\\",\\\"2021-06-23 08:00:00\\\",\\\"2021-06-23 14:00:00\\\",\\\"2021-06-23 20:00:00\\\",\\\"2021-06-24 02:00:00\\\",\\\"2021-06-24 08:00:00\\\",\\\"2021-06-24 14:00:00\\\",\\\"2021-06-24 20:00:00\\\",\\\"2021-06-25 02:00:00\\\",\\\"2021-06-25 08:00:00\\\",\\\"2021-06-25 14:00:00\\\",\\\"2021-06-25 20:00:00\\\",\\\"2021-06-26 02:00:00\\\",\\\"2021-06-26 08:00:00\\\",\\\"2021-06-26 14:00:00\\\",\\\"2021-06-26 20:00:00\\\",\\\"2021-06-27 02:00:00\\\",\\\"2021-06-27 08:00:00\\\",\\\"2021-06-27 14:00:00\\\",\\\"2021-06-27 20:00:00\\\",\\\"2021-06-28 02:00:00\\\",\\\"2021-06-28 08:00:00\\\",\\\"2021-06-28 14:00:00\\\",\\\"2021-06-28 20:00:00\\\",\\\"2021-06-29 02:00:00\\\",\\\"2021-06-29 08:00:00\\\",\\\"2021-06-29 14:00:00\\\",\\\"2021-06-29 20:00:00\\\",\\\"2021-06-30 02:00:00\\\",\\\"2021-06-30 08:00:00\\\",\\\"2021-06-30 14:00:00\\\",\\\"2021-06-30 20:00:00\\\",\\\"2021-07-01 02:00:00\\\",\\\"2021-07-01 08:00:00\\\",\\\"2021-07-01 14:00:00\\\",\\\"2021-07-01 20:00:00\\\",\\\"2021-07-02 02:00:00\\\",\\\"2021-07-02 08:00:00\\\",\\\"2021-07-02 14:00:00\\\",\\\"2021-07-02 20:00:00\\\",\\\"2021-07-03 02:00:00\\\",\\\"2021-07-03 08:00:00\\\",\\\"2021-07-03 14:00:00\\\",\\\"2021-07-03 20:00:00\\\",\\\"2021-07-04 02:00:00\\\",\\\"2021-07-04 08:00:00\\\",\\\"2021-07-04 14:00:00\\\",\\\"2021-07-04 20:00:00\\\",\\\"2021-07-05 02:00:00\\\",\\\"2021-07-05 08:00:00\\\",\\\"2021-07-05 14:00:00\\\",\\\"2021-07-05 20:00:00\\\",\\\"2021-07-06 02:00:00\\\",\\\"2021-07-06 08:00:00\\\",\\\"2021-07-06 14:00:00\\\",\\\"2021-07-06 20:00:00\\\",\\\"2021-07-07 02:00:00\\\",\\\"2021-07-07 08:00:00\\\",\\\"2021-07-07 14:00:00\\\",\\\"2021-07-07 20:00:00\\\",\\\"2021-07-08 02:00:00\\\",\\\"2021-07-08 08:00:00\\\",\\\"2021-07-08 14:00:00\\\",\\\"2021-07-08 20:00:00\\\",\\\"2021-07-09 02:00:00\\\",\\\"2021-07-09 08:00:00\\\",\\\"2021-07-09 14:00:00\\\",\\\"2021-07-09 20:00:00\\\",\\\"2021-07-10 02:00:00\\\",\\\"2021-07-10 08:00:00\\\",\\\"2021-07-10 14:00:00\\\",\\\"2021-07-10 20:00:00\\\",\\\"2021-07-11 02:00:00\\\",\\\"2021-07-11 08:00:00\\\",\\\"2021-07-11 14:00:00\\\",\\\"2021-07-11 20:00:00\\\",\\\"2021-07-12 02:00:00\\\",\\\"2021-07-12 08:00:00\\\",\\\"2021-07-12 14:00:00\\\",\\\"2021-07-12 20:00:00\\\",\\\"2021-07-13 02:00:00\\\",\\\"2021-07-13 08:00:00\\\",\\\"2021-07-13 14:00:00\\\",\\\"2021-07-13 20:00:00\\\",\\\"2021-07-14 02:00:00\\\",\\\"2021-07-14 08:00:00\\\",\\\"2021-07-14 14:00:00\\\",\\\"2021-07-14 20:00:00\\\",\\\"2021-07-15 02:00:00\\\",\\\"2021-07-15 08:00:00\\\",\\\"2021-07-15 14:00:00\\\",\\\"2021-07-15 20:00:00\\\",\\\"2021-07-16 02:00:00\\\",\\\"2021-07-16 08:00:00\\\",\\\"2021-07-16 14:00:00\\\",\\\"2021-07-16 20:00:00\\\",\\\"2021-07-17 02:00:00\\\",\\\"2021-07-17 08:00:00\\\"]\",\"Pa\":\"[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]\",\"q\":\"[]\",\"CalculatedType\":\"1\",\"runoffSim\":\"[]\",\"KD\":\"[0.93, 0.93, 0.93, 0.93, 0.93, 0.93, 0.95, 0.96, 0.96, 0.96, 0.96, 0.96]\",\"clen\":\"6\",\"PA0\":\"25.4\"}";
        Map data = JSON.parseObject(a, Map.class);
        P_RZHJR obj = new P_RZHJR(data);
        System.out.println(obj.predict());
    }
}